﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Web;

namespace CNative.WebApi.Utils
{
    /// <summary>
    /// 服务帮助类
    /// </summary>
    public class ServiceHelper
    {
        public static ConcurrentDictionary<Type, object> _dict = new ConcurrentDictionary<Type, object>();

        /// <summary>
        /// 获取对象
        /// </summary>
        public static T Get<T>() where T : new()
        {
            Type type = typeof(T);
            object obj = _dict.GetOrAdd(type, (key) => new T());

            return (T)obj;
        }

        /// <summary>
        /// 获取对象
        /// </summary>
        public static T Get<T>(Func<T> func) where T : new()
        {
            Type type = typeof(T);
            object obj = _dict.GetOrAdd(type, (key) => func());

            return (T)obj;
        }
        #region GetAppSettingsVal
        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <param name="defaultVal"></param>
        /// <returns></returns>
        public static string GetAppSettingsVal(string key, string defaultVal = "", string configPath = "")
        {
            try
            {
                return ConfigHelper.GetAppSettings(key, defaultVal, configPath);
            }
            catch { return defaultVal; }
        }
        #endregion
        #region 启动一个独立进程
        /// <summary>
        /// 启动一个独立进程
        /// </summary>
        /// <param name="ServiceFullName"></param>
        /// <param name="command"></param>
        /// <returns></returns>
        public static string RunExe(string ServiceFullName, string command)
        {
            Process p = new Process(); //实例一个Process类，启动一个独立进程
            try
            {
                p.StartInfo.FileName = ServiceFullName;  //设定程序名
                p.StartInfo.Arguments = command;  //设定程式执行参数   
                p.StartInfo.UseShellExecute = false;    //关闭Shell的使用
                p.StartInfo.RedirectStandardInput = true;  //重定向标准输入
                p.StartInfo.RedirectStandardOutput = true; //重定向标准输出  
                p.StartInfo.RedirectStandardError = true;   //重定向错误输出         
                p.StartInfo.CreateNoWindow = true;  //设置不显示窗口
                p.Start();    //启动

                return p.StandardOutput.ReadToEnd(); //从输出流取得命令执行结果
            }
            catch (Exception ex) { return ex.ToString(); }
            finally { try { p.Close(); } catch { } }
        }
        /// <summary> 
        /// 执行CMD语句 
        /// </summary> 
        /// <param name="cmd">要执行的CMD命令</param> 
        public static void RunCmd(string cmd)
        {
            try
            {
                var proc = new Process();
                proc.StartInfo.CreateNoWindow = true;
                proc.StartInfo.FileName = "cmd.exe";
                proc.StartInfo.UseShellExecute = false;
                proc.StartInfo.RedirectStandardError = true;
                proc.StartInfo.RedirectStandardInput = true;
                proc.StartInfo.RedirectStandardOutput = true;
                proc.Start();
                proc.StandardInput.WriteLine(cmd);
                proc.Close();
            }
            catch (Exception ex)
            {
                LogUtil.Error(ex.ToString());
            }
        }
        #endregion
        #region SleepFunc
        /// <summary>
        /// 进程暂停,endfunc返回true时结束
        /// </summary>
        /// <param name="endfunc">返回true时结束</param>
        /// <param name="IntervalTime">秒</param>
        /// <returns></returns>
        public static bool SleepFunc(Func<bool> endfunc, int IntervalTime = 60)
        {
            bool flag = true;
            try
            {
                for (int i = 0; i < IntervalTime; i++)
                {
                    System.Threading.Thread.Sleep(1000);
                    if (endfunc())
                    {
                        break;
                    }
                    if (i == (IntervalTime - 1))
                    {
                        flag = false;
                    }
                }
            }
            catch (Exception ex)
            {
                LogUtil.Error(ex.ToString());
                flag = false;
            }
            return flag;
        }
        #endregion

        #region 计算文件大小函数
        /// <summary>
        /// 计算文件大小函数(保留两位小数),Size为字节大小
        /// </summary>
        /// <param name="size">初始文件大小</param>
        /// <returns></returns>
        public static string GetFileSize(long size)
        {
            var num = 1024.00; //byte

            if (size < num)
                return size + "B";
            if (size < Math.Pow(num, 2))
                return (size / num).ToString("f2") + "K"; //kb
            if (size < Math.Pow(num, 3))
                return (size / Math.Pow(num, 2)).ToString("f2") + "M"; //M
            if (size < Math.Pow(num, 4))
                return (size / Math.Pow(num, 3)).ToString("f2") + "G"; //G

            return (size / Math.Pow(num, 4)).ToString("f2") + "T"; //T
        }
        #endregion
        #region 获取文件名
        /// <summary>
        /// 获取文件名，不包括扩展名
        /// </summary>
        /// <param name="ServiceFullName"></param>
        /// <returns></returns>
        public static string GetFileName(string ServiceFullName)
        {
            if (!string.IsNullOrEmpty(ServiceFullName))
            {
                var ServiceName = ServiceFullName.Substring(ServiceFullName.LastIndexOf('\\') + 1);//只到程序名称，不带.exe
                return ServiceName.Substring(0, ServiceName.LastIndexOf('.'));
            }
            else return "";
        }
        /// <summary>
        /// 获取文件路径
        /// </summary>
        /// <param name="ServiceFullName"></param>
        /// <returns></returns>
        public static string GetFilePath(string ServiceFullName)
        {
            if (!string.IsNullOrEmpty(ServiceFullName))
                return ServiceFullName.Substring(0, ServiceFullName.LastIndexOf('\\') + 1);
            else return "";
        }
        #endregion
        #region IsWow64Process
        [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool IsWow64Process(
            [In] IntPtr hProcess,
            [Out] out bool wow64Process
        );
        public static bool CurrentIsWow64Process()
        {
            if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) ||
                Environment.OSVersion.Version.Major >= 6)
            {
                using (Process p = Process.GetCurrentProcess())
                {
                    return IsWow64Process(p);
                }
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 检测当前程序运行的是64位机器还是32位
        /// </summary>
        /// <param name="pName">进程路径</param>
        /// <returns></returns>
        public static bool IsWow64Process(string pFullName)
        {
            try
            {
                //获取当前运行程序完全限定名 
                var currentModuleName = GetFileName(pFullName);
                //获取进程名为ProcessName的Process数组。 
                Process[] processes = Process.GetProcessesByName(currentModuleName);
                //遍历有相同进程名称正在运行的进程 
                foreach (Process process in processes)
                {
                    try
                    {
                        if (process.MainModule.FileName.Trim().ToLower() == pFullName.Trim().ToLower())
                        {
                            return IsWow64Process(process);
                        }
                    }
                    catch (Exception ex) { LogUtil.Error(ex.ToString()); }
                }
            }
            catch (Exception ex) { LogUtil.Error(ex.ToString()); }
            return false;
        }
        /// <summary>
        /// 检测当前程序运行的是64位机器还是32位
        /// </summary>
        /// <param name="p">进程</param>
        /// <returns></returns>
        public static bool IsWow64Process(Process p)
        {
            try
            {
                if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) ||
                    Environment.OSVersion.Version.Major >= 6)
                {
                    bool retVal;
                    if (!IsWow64Process(p.Handle, out retVal))
                    {
                        return true;
                    }
                    return retVal == false;
                }
            }
            catch (Exception ex) { LogUtil.Error(ex.ToString()); }
            return true;
        }
        #endregion
        #region CloseCurrentProcess
        /// <summary>
        ///  结束进程 Boolean : judgement current program is running
        /// </summary>
        /// <returns></returns>
        public static void CloseCurrentProcess(string currentModuleName = "", bool IsAll = false)
        {
            try
            {
                Process currentProcess = Process.GetCurrentProcess(); //获取当前进程 
                if (string.IsNullOrEmpty(currentModuleName))
                {
                    //获取当前运行程序完全限定名 
                    currentModuleName = currentProcess.ProcessName;
                }
                //获取进程名为ProcessName的Process数组。 
                Process[] processes = Process.GetProcessesByName(currentModuleName);
                //遍历有相同进程名称正在运行的进程 
                foreach (Process process in processes)
                {
                    try
                    {
                        if (IsAll || process.Id == currentProcess.Id)
                        { //根据进程ID排除当前进程 
                            process.Kill();
                        }
                    }
                    catch { }
                }
            }
            catch { }
        }
        public static bool ExistsProcess(string currentModuleName)
        {
            try
            {
                //获取进程名为ProcessName的Process数组。 
                var processes = Process.GetProcessesByName(currentModuleName);
                //遍历有相同进程名称正在运行的进程 
                if (processes != null && processes.Length > 0)
                    return true;
            }
            catch { }
            return false;
        }
        #endregion
        #region 打开所在文件夹
        /// <summary>
        /// 打开所在文件夹
        /// </summary>
        public static void OpenFullPath(string FullName)
        {
            try
            {
                if (!string.IsNullOrEmpty(FullName))
                {
                    //打开文件所属文件夹
                    System.Diagnostics.Process.Start("explorer.exe", "/select," + FullName);
                }
            }
            catch (Exception ex)
            {
                LogUtil.Error(ex.ToString());
            }
        }
        /// <summary>
        /// 清空指定文件夹
        /// </summary>
        /// <param name="dirPath"></param>
        public static void ClearDirectory(string dirPath)
        {
            try
            {
                if (!Directory.Exists(dirPath))
                    Directory.CreateDirectory(dirPath);

                string[] files = Directory.GetFiles(dirPath);
                foreach (string str in files)
                {
                    File.Delete(str);
                }
                foreach (string str2 in Directory.GetDirectories(dirPath))
                {
                    DeleteDirectory(str2);
                }
            }
            catch (Exception ex)
            {
                LogUtil.Error(ex.ToString());
            }
        }

        /// <summary>
        /// 删除文件夹
        /// </summary>
        /// <param name="dirPath"></param>
        public static void DeleteDirectory(string dirPath)
        {
            try
            {
                foreach (string str in Directory.GetFiles(dirPath))
                {
                    File.Delete(str);
                }
                foreach (string str2 in Directory.GetDirectories(dirPath))
                {
                    DeleteDirectory(str2);
                }
                DirectoryInfo info = new DirectoryInfo(dirPath);
                info.Refresh();
                if ((info.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                {
                    info.Attributes &= ~FileAttributes.ReadOnly;
                }
                info.Delete();
            }
            catch (Exception ex)
            {
                LogUtil.Error(ex.ToString());
            }
        }
        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="filePath"></param>
        public static void DeleteFile(string filePath)
        {
            try
            {
                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                }
            }
            catch (Exception ex)
            {
                LogUtil.Error(ex.ToString());
            }
        }
        #endregion

        #region SoapReceiversAdd/SoapReceiversClear
        /// <summary>
        /// 添加Web Service服务
        /// </summary>
        /// <param name="port"></param>
        /// <param name="serviceName"></param>
        /// <param name="serviceType"></param>
        public static void SoapReceiversAdd(string wsService, string serviceType)
        {
            try
            {
                Assembly assembly = null;
                Type svcType = null;
                var dllPath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Controllers");
                try
                {
                    var ab = Assembly.GetEntryAssembly();
                    svcType = Type.GetType(serviceType, true, true);
                    if (svcType == null)
                        svcType = ab.GetType(serviceType, true, true);
                    if (svcType != null)
                    {
                        assembly = ab;
                    }
                }
                catch (Exception ex)
                {
                    //LogUtil.Error("插件：" + dllPath + serviceType + "初始化失败！\r\t" + ex);
                }
                try
                {
                    if (assembly == null)
                        assembly = AssemblyHelper.AssemblyLoad(serviceType, dllPath);
                    if (svcType == null && assembly != null)
                        svcType = assembly.GetType(serviceType, true, true);
                    //if (obj == null && svcType != null)
                    //    obj = FastReflection.FastInstance(type, args);// Activator.CreateInstance(type);

                }
                catch (Exception ex)
                {
                    LogUtil.Error("插件：" + dllPath + serviceType + "初始化失败！\r\t" + ex);
                    return;
                }
                if (svcType != null)
                {
                    //Uri address = new Uri("soap.tcp://localhost/HelloService");

                    Uri address = new Uri("soap.tcp://"+ wsService);
                    var er = new Microsoft.Web.Services3.Addressing.EndpointReference(address);

                    Microsoft.Web.Services3.Messaging.SoapReceivers.Add(er, svcType);

                    LogUtil.Debug("Web Service 服务 启动成功,Address=" + address.ToString()+ ",serviceType=" + serviceType.ToString());
                }
            }
            catch (Exception ex)
            {
                LogUtil.Error(ex.ToString());
            }
        }
        /// <summary>
        /// 执行停止Web Service服务
        /// </summary>
        public static void SoapReceiversClear()
        {
            try
            {
                Microsoft.Web.Services3.Messaging.SoapReceivers.Clear();
            }
            catch (Exception ex)
            {
                LogUtil.Error(ex.ToString());
            }
        }
        #endregion
    }
}